package com.cn.plugin.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.sql.Connection;
import java.util.Objects;
import java.util.Properties;

/**
 * @author : Hydra
 * @date: 2021/3/10 10:43
 * @version: 1.0
 */
@Slf4j
@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
})
public class StatementPlugin implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("Statement Plugin 拦截 :" + invocation.getMethod());

        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);

        /**
         * 先解释下为什么写成delegate.boundSql就可以拿到boundSql类
         * 从前面也可以得知，statementHandler的默认实现是routingStatementHandler。
         * 这个类有一个属性statementHandler，属性名就叫delegate，而这个属性的默认实现又是preparedStatementHandler
         * 后面这个类又有属性boundSql，所以，最终形成的写法就是delegate.boundSql。
         * 所以这也体现了MetaObject工具类的强大，可以通过实例传参，就可以根据属性名获取对应属性值
         */

//        String originalSql = (String) metaObject.getValue("delegate.boundSql.sql");
//        System.out.println("==> BOUND SQL:"+originalSql);
//        metaObject.setValue("delegate.boundSql.sql",originalSql+ " and money=?");

        //如果写了上面的sql，那么下面这两行会失效
        metaObject.setValue("delegate.rowBounds.offset", 0);
        metaObject.setValue("delegate.rowBounds.limit", 2);
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        if(target instanceof StatementHandler)
            return Plugin.wrap(target, this);
        return target;
    }

    @Override
    public void setProperties(Properties properties) {
        if (Objects.nonNull(properties))
            System.out.println("插件配置的信息：" + properties);
    }
}
